package testCases;

import java.awt.image.WritableRaster;
import java.util.Random;

/**
 * @projectName: code-snippet
 * @className: Pattern
 * @description:
 * @author: JLONG
 * @date: 2024/9/10 16:06
 * @version: 1.0
 */
public enum Pattern {
    WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return 255;
        }
    },
    BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return 0;
        }
    },
    RED {
        public int getValue(int x, int y, int b, int w, int h) {
            return b == 0 ? 255 : 0;
        }
    },
    YELLOW {
        public int getValue(int x, int y, int b, int w, int h) {
            return b != 0 && b != 1 ? 0 : 255;
        }
    },
    HORIZONTAL_BLACK_RED_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (y / 8 % 3) {
                case 0:
                    return 0;
                case 1:
                    return b == 0 ? 255 : 0;
                case 2:
                    return 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    HORIZONTAL_BLACK_YELLOW_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (y / 8 % 3) {
                case 0:
                    return 0;
                case 1:
                    return b != 0 && b != 1 ? 0 : 255;
                case 2:
                    return 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    HORIZONTAL_BLACK_WHITE_RED_YELLOW {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (y / 8 % 4) {
                case 0:
                    return 0;
                case 1:
                    return 255;
                case 2:
                    return b == 0 ? 255 : 0;
                case 3:
                   return b != 0 && b != 1 ? 0 : 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    VERTICAL_BLACK_RED_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (x / 8 % 3) {
                case 0:
                    return 0;
                case 1:
                    return b == 0 ? 255 : 0;
                case 2:
                    return 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    VERTICAL_BLACK_YELLOW_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (x / 8 % 3) {
                case 0:
                    return 0;
                case 1:
                    return b != 0 && b != 1 ? 0 : 255;
                case 2:
                    return 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    VERTICAL_BLACK_WHITE_RED_YELLOW {
        public int getValue(int x, int y, int b, int w, int h) {
            switch (x / 8 % 4) {
                case 0:
                    return 0;
                case 1:
                    return 255;
                case 2:
                    return b == 0 ? 255 : 0;
                case 3:
                   return b != 0 && b != 1 ? 0 : 255;
                default:
                    throw new AssertionError();
            }
        }
    },
    BIT_CHECKERED {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x + y) % 2 == 0 ? 0 : 255;
        }
    },
    BIT_CHECKERED_RED_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x + y) % 2 == 0 ? (b == 0 ? 255 : 0) : 255;
        }
    },
    BIT_CHECKERED_YELLOW_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x + y) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 255;
        }
    },
    BIT_CHECKERED_RED_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x + y) % 2 == 0 ? (b == 0 ? 255 : 0) : 0;
        }
    },
    BIT_CHECKERED_YELLOW_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x + y) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 0;
        }
    },
    BYTE_CHECKERED {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 8 + y / 8) % 2 == 0 ? 0 : 255;
        }
    },
    BYTE_CHECKERED_RED_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 8 + y / 8) % 2 == 0 ? (b == 0 ? 255 : 0) : 255;
        }
    },
    BYTE_CHECKERED_YELLOW_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 8 + y / 8) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 255;
        }
    },
    BYTE_CHECKERED_RED_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 8 + y / 8) % 2 == 0 ? (b == 0 ? 255 : 0) : 0;
        }
    },
    BYTE_CHECKERED_YELLOW_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 8 + y / 8) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 0;
        }
    },
    CHECKERED_16_PIXEL {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 16 + y / 16) % 2 == 0 ? 0 : 255;
        }
    },
    CHECKERED_16_PIXEL_RED_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 16 + y / 16) % 2 == 0 ? (b == 0 ? 255 : 0) : 255;
        }
    },
    CHECKERED_16_PIXEL_YELLOW_WHITE {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 16 + y / 16) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 255;
        }
    },
    CHECKERED_16_PIXEL_RED_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 16 + y / 16) % 2 == 0 ? (b == 0 ? 255 : 0) : 0;
        }
    },
    CHECKERED_16_PIXEL_YELLOW_BLACK {
        public int getValue(int x, int y, int b, int w, int h) {
            return (x / 16 + y / 16) % 2 == 0 ? (b != 0 && b != 1 ? 0 : 255) : 0;
        }
    },
    TESTPATTERN_FOR_MEASUREMENTS_MONOCHROM {
        public int getValue(int x, int y, int b, int w, int h) {
            double margin = 0.375;
            return !((double)y < (double)h * margin) && !((double)y > (double)h * (1.0 - margin)) ? Pattern.BYTE_CHECKERED.getValue(x, y, b, w, h) : 0;
        }
    },
    TESTPATTERN_FOR_MEASUREMENTS_BLACK_WHITE_RED {
        public int getValue(int x, int y, int b, int w, int h) {
            double margin = 0.3;
            return !((double)y < (double)h * margin) && !((double)y > (double)h * (1.0 - margin)) ? Pattern.BYTE_CHECKERED_RED_WHITE.getValue(x, y, b, w, h) : 0;
        }
    },
    TESTPATTERN_FOR_MEASUREMENTS_BLACK_WHITE_YELLOW {
        public int getValue(int x, int y, int b, int w, int h) {
            double margin = 0.3;
            return !((double)y < (double)h * margin) && !((double)y > (double)h * (1.0 - margin)) ? Pattern.BYTE_CHECKERED_YELLOW_WHITE.getValue(x, y, b, w, h) : 0;
        }
    },
    RANDOM_BLACK_WHITE {
        public void updateRaster(WritableRaster raster, int i, int width, int height) {
            for(int y = 0; y < height; ++y) {
                for(int x = 0; x < width; ++x) {
                    Pattern pattern = Pattern.RANDOM_BLACK_WHITE_PATTERNS[Pattern.RANDOM.nextInt(2)];

                    for(int b = 0; b < 3; ++b) {
                        raster.setSample(x, y, b, pattern.getValue(x, y, b, width, height));
                    }
                }
            }

        }

        public int getValue(int x, int y, int b, int w, int h) {
            return 0;
        }
    },
    RANDOM_BLACK_WHITE_RED {
        public void updateRaster(WritableRaster raster, int i, int width, int height) {
            for(int y = 0; y < height; ++y) {
                for(int x = 0; x < width; ++x) {
                    Pattern pattern = Pattern.RANDOM_BLACK_WHITE_RED_PATTERNS[Pattern.RANDOM.nextInt(3)];

                    for(int b = 0; b < 3; ++b) {
                        raster.setSample(x, y, b, pattern.getValue(x, y, b, width, height));
                    }
                }
            }

        }

        public int getValue(int x, int y, int b, int w, int h) {
            return 0;
        }
    },
    RANDOM_BLACK_WHITE_YELLOW {
        public void updateRaster(WritableRaster raster, int i, int width, int height) {
            for(int y = 0; y < height; ++y) {
                for(int x = 0; x < width; ++x) {
                    Pattern pattern = Pattern.RANDOM_BLACK_WHITE_YELLOW_PATTERNS[Pattern.RANDOM.nextInt(3)];

                    for(int b = 0; b < 3; ++b) {
                        raster.setSample(x, y, b, pattern.getValue(x, y, b, width, height));
                    }
                }
            }

        }

        public int getValue(int x, int y, int b, int w, int h) {
            return 0;
        }
    },
    RANDOM_BLACK_WHITE_RED_YELLOW{
        public void updateRaster(WritableRaster raster, int i, int width, int height) {
            for(int y = 0; y < height; ++y) {
                for(int x = 0; x < width; ++x) {
                    Pattern pattern = Pattern.RANDOM_BLACK_WHITE_RED_YELLOW_PATTERNS[Pattern.RANDOM.nextInt(4)];
                    for(int b = 0; b < 3; ++b) {
                        raster.setSample(x, y, b, pattern.getValue(x, y, b, width, height));
                    }
                }
            }
        }
        public int getValue(int x, int y, int b, int w, int h) {
            return 0;
        }
    },
    BWRY_8BIT_CHECK{
        public int getValue(int x, int y, int b, int w, int h) {
            return switch (y % 4) {
                case 0 -> x % 2 == 0 ? 255 : (b == 2 ? 0 : 255);
                case 1 -> x % 2 == 0 ? (b == 0 ? 255 : 0) : 0;
                case 2 -> x % 2 == 0 ? (b == 2 ? 0 : 255) : 255;
                case 3 -> x % 2 == 0 ? 0 : (b == 0 ? 255 : 0);
                default -> throw new AssertionError();
            };
        }
    };

    private static final Random RANDOM = new Random();
    private static final Pattern[] RANDOM_BLACK_WHITE_PATTERNS = new Pattern[]{WHITE, BLACK};
    private static final Pattern[] RANDOM_BLACK_WHITE_RED_PATTERNS = new Pattern[]{WHITE, BLACK, RED};
    private static final Pattern[] RANDOM_BLACK_WHITE_YELLOW_PATTERNS = new Pattern[]{WHITE, BLACK, YELLOW};
    private static final Pattern[] RANDOM_BLACK_WHITE_RED_YELLOW_PATTERNS = new Pattern[]{WHITE, BLACK, RED, YELLOW};

    private Pattern() {
    }

    public abstract int getValue(int var1, int var2, int var3, int var4, int var5);

    public void updateRaster(WritableRaster raster, int i, int width, int height) {
        for(int y = 0; y < height; ++y) {
            for(int x = 0; x < width; ++x) {
                for(int b = 0; b < 3; ++b) {
                    raster.setSample(x, y, b, this.getValue(x, y, b, width, height));
                }
            }
        }

    }
}
